#include "../sleek/core/define.h"
#include "GameCore.h"
#include "Physic.h"

namespace interne
{
    Physic::Physic(GameCore *mom) : core(mom)
    {
        timespec = 1/60.f;
        world = new b2World(b2Vec2(0,-9.82));
        world->SetDebugDraw(new DebugDraw(core->everythink->getDrawManager()));
    }
    Physic::~Physic()
    {
        delete world;
    }
    void Physic::setWorld(b2World *w)
    {
        delete world;
        world = w;
        world->SetDebugDraw(new DebugDraw(core->everythink->getDrawManager()));
    }
    void Physic::createPlayer(Entity *tmp)
    {
        b2BodyDef def;
            def.type = b2_dynamicBody;
            def.fixedRotation = true;
            def.allowSleep = false;

        sleek::core::math::vector2du size(tmp->getTexture()->getOriginalSize().width/5,
                                          tmp->getTexture()->getOriginalSize().height/2.2);
        createBox(tmp, def, size);
    }
    void Physic::createDynamicBox(Entity *tmp)
    {
        if(!tmp || !tmp->getTexture()) return;
        b2BodyDef def;
            def.type = b2_dynamicBody;
            def.fixedRotation = false;
            def.allowSleep = false;
        createBox(tmp, def, tmp->getTexture()->getOriginalSize()/2);
    }
    void Physic::createStaticBox(Entity *tmp)
    {
        if(!tmp || !tmp->getTexture()) return;
        b2BodyDef def;
            def.fixedRotation = false;
        createBox(tmp, def, tmp->getTexture()->getOriginalSize()/2);
    }
    void Physic::createVirtual(Entity *tmp)
    {
        b2BodyDef def;
        def.position.Set(tmp->env->getPosition().x,tmp->env->getPosition().y);
        def.angle = tmp->env->getRotation().z/180*sleek::core::PI;

        tmp->phy = world->CreateBody(&def);
        tmp->phy->SetFixedRotation(def.fixedRotation);
        tmp->phy->SetUserData(tmp);
    }
    void Physic::createBox(Entity *tmp, b2BodyDef def, sleek::core::math::vector2du size)
    {
        def.position.Set(tmp->env->getPosition().x,tmp->env->getPosition().y);
        def.angle = tmp->env->getRotation().z/180*sleek::core::PI;

        tmp->phy = world->CreateBody(&def);
        tmp->phy->SetFixedRotation(def.fixedRotation);
        tmp->phy->SetUserData(tmp);

        b2PolygonShape shape;
        shape.SetAsBox(size.width*tmp->env->getScale().x,size.height*tmp->env->getScale().y);

        tmp->fix = tmp->phy->CreateFixture(&shape, 1.f);
    }
    void Physic::createCircle(Entity *tmp, b2BodyDef def, sleek::core::math::vector2du size)
    {
        def.position.Set(tmp->env->getPosition().x,tmp->env->getPosition().y);
        def.angle = tmp->env->getRotation().z/180*sleek::core::PI;

        tmp->phy = world->CreateBody(&def);
        tmp->phy->SetFixedRotation(def.fixedRotation);
        tmp->phy->SetUserData(tmp);

        b2PolygonShape shape;

        b2Vec2 *vertices = new b2Vec2[17];
        const float32 k_segments = 16.0f;
        const float32 k_increment = 2.0f * b2_pi / k_segments;
        float32 theta = 0.0f;
        for (int32 i = 0; i < k_segments; ++i)
        {
            vertices[i] = b2Vec2(size.width*cosf(theta), size.height*sinf(theta));
            theta += k_increment;
        }

        shape.Set(vertices, 16);

        tmp->fix = tmp->phy->CreateFixture(&shape, 1.f);
    }
    void Physic::debug()
    {
//        core->everythink->getDrawManager()->ObjectRenderBegin();
        world->DrawDebugData();
//        core->everythink->getDrawManager()->ObjectRenderEnd();
    }
    void Physic::step()
    {
        time_stamp.update_begin();
//        if(time_stamp.getElapsedTime() > 1/24)
//        {
            world->Step(1.f/core->screen->getFPS()*4,6,2);
            for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
            {
                if (b->GetUserData() != NULL)
                {
                    Entity *tmp = (Entity*)b->GetUserData();
                    tmp->update(b->GetPosition(), b->GetAngle()*180/sleek::core::PI);
                }
            }
//            time_stamp.update_end();
//        }
    }
}
